package com.booter.webflux.controller;

import com.booter.webflux.model.Menu;
import com.booter.webflux.repository.mongo.MenuMongoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Date;
import java.util.UUID;

@RestController
@RequestMapping("mongo")
public class MongoController {

    @Autowired
    private MenuMongoRepository repository;

    @Autowired
    private ReactiveMongoTemplate reactiveMongoTemplate;

    @RequestMapping(value = "menu/id2")
    public Flux<Menu> getById2(@RequestParam String id) {
        Query query = new Query();
        Criteria criteria = new Criteria();
        criteria.and("_id").is(id);
        query.addCriteria(criteria);

//        事务实现方式 ，从spring data mongo 2.2开始改用TransactionalOperator 和@Transactional 实现事务
//        reactiveMongoTemplate.inTransaction()
//                .execute(action -> action.insert(user1)
//                        .then(action.insert(user2)));
        return this.reactiveMongoTemplate.find(query, Menu.class);
    }


    @RequestMapping(value = "menu/list", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Menu> findAll() {
        return this.repository.findAll();
    }


    @RequestMapping(value = "menu/save")
    public Mono<Menu> save(@RequestBody Mono<Menu> menu) {
        return menu.flatMap(s -> {

            //若不强制设置id ，spring data mongo 会无法根据id查询数据
            //mongo默认生成的主键为objectId
            s.setId(UUID.randomUUID().toString());
            s.setCreateTime(new Date());
            return this.repository.insert(s);
        });
    }

    @RequestMapping(value = "menu/save2")
    public Mono<Menu> save2(@RequestBody Mono<Menu> menu) {
        return menu.flatMap(s -> {
            s.setId(UUID.randomUUID().toString());
            s.setCreateTime(new Date());
            return this.repository.insert(s);
        });
    }

    public static void main(String[] args) {
//        var str = "这是一个字符串类型的数据";     // 等价于  String str = "这是一个字符串类型的数据";
//        System.out.println(str);    // java编译器会自动根据str变量右边的数据类型来匹配
    }


    @RequestMapping(value = "menu/update")
    public Mono<Menu> update(@RequestBody Menu menu) {

        return this.repository.findById(menu.getId()).flatMap(t -> {
            if (StringUtils.isEmpty(menu.getId())) {
                return Mono.justOrEmpty(new Menu());
            }
            return this.repository.save(t).then(Mono.just(new Menu("1")));
        }).defaultIfEmpty(new Menu("2"));
    }

    @RequestMapping(value = "menu/id")
    public Mono<Menu> getById(@RequestParam String id) {
        return this.repository.findById(id);
    }

    @RequestMapping(value = "menu/delete")
    public Mono<ResponseEntity<Void>> delete(@RequestParam String id) {
        return this.repository.findById(id)
                .flatMap(s -> this.repository.deleteById(id)
                        .then(Mono.just(new ResponseEntity<Void>(HttpStatus.OK))))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND))
                ;
    }
}
